﻿using System.Collections.Generic;
using System.Threading;


namespace RemoteData.core.queue
{
    public class SHQueue<T>
    {
        private Queue<T> _tasks = new Queue<T>();

        private Semaphore fullSemphore;
        private Semaphore emptySemphore;

        // 为保证线程安全，使用一个锁来保护_task的访问
        private readonly object _locker = new object();

        // 通过 _wh 给工作线程发信号
        private EventWaitHandle _wh = new AutoResetEvent(false);

        public SHQueue()
        {
            fullSemphore = new Semaphore(0, 10000);
            emptySemphore = new Semaphore(10000, 10000);
        }

        public SHQueue(int size)
        {
            fullSemphore = new Semaphore(0, size);
            emptySemphore = new Semaphore(size, size);
            _tasks = new Queue<T>(size);
        }

        //public void Enqueue(T data)
        //{
        //    lock (_locker)
        //    {
        //        _tasks.Enqueue(data);  //向队列中插入任务
        //        if (_tasks.Count() > 0)
        //        {
        //            Console.WriteLine("counts == {0}", _tasks.Count());
        //        }
        //        else
        //        {
        //            Console.WriteLine("counts == 0");
        //        }
        //        _wh.Set();  // 给工作线程发信号
        //    }
        //}



        public T Peak()
        {
            T data = default(T);

            lock (_locker)
            {
                if (_tasks.Count > 0)
                {
                    data = _tasks.Peek();
                }
            }
            return data;
        }

        public void Enqueue(T data)
        {
            emptySemphore.WaitOne();

            lock (_locker)
            {
                _tasks.Enqueue(data);  //向队列中插入任务
            }

            fullSemphore.Release();
        }

        public void TryEnqueue(T data, int milliSecondTimeOut)
        {
            bool recvBreakSignal = emptySemphore.WaitOne(milliSecondTimeOut);
            if (!recvBreakSignal)
            {
                return;
            }

            lock (_locker)
            {
                _tasks.Enqueue(data);  //向队列中插入任务
            }

            fullSemphore.Release();
        }


        public T Dequeue()
        {
            T data = default(T);

            fullSemphore.WaitOne();

            lock (_locker)
            {
                data = _tasks.Dequeue(); // 有任务时，出列任务
            }

            emptySemphore.Release();

            return data;
        }

        public bool TryDequeue(out T data, int milliSecondTimeOut)
        {
            data = default(T);

            bool recvBreakSignal = fullSemphore.WaitOne(milliSecondTimeOut);
            if (!recvBreakSignal)
            {
                return false;
            }

            lock (_locker)
            {
                data = _tasks.Dequeue(); // 有任务时，出列任务
            }

            emptySemphore.Release();

            return true;
        }

        public int GetCounts()
        {
            lock (_locker)
            {
                return _tasks.Count;
            }
        }

        public bool isEmpty()
        {

            lock (_locker)
            {
                return _tasks.Count > 0 ? false : true;
            }
        }

        public void Clear()
        {

            lock (_locker)
            {
                _tasks.Clear();
            }
        }
    }
}
